/*********************************************************************************************************************
 * CYT4BB Opensourec Library 即（ CYT4BB 开源库）是一个基于官方 SDK
 *接口的第三方开源库 Copyright (c) 2022 SEEKFREE 逐飞科技
 *
 * 本文件是 CYT4BB 开源库的一部分
 *
 * CYT4BB 开源库 是免费软件
 * 您可以根据自由软件基金会发布的 GPL（GNU General Public License，即
 *GNU通用公共许可证）的条款 即 GPL 的第3版（即
 *GPL3.0）或（您选择的）任何后来的版本，重新发布和/或修改它
 *
 * 本开源库的发布是希望它能发挥作用，但并未对其作任何的保证
 * 甚至没有隐含的适销性或适合特定用途的保证
 * 更多细节请参见 GPL
 *
 * 您应该在收到本开源库的同时收到一份 GPL 的副本
 * 如果没有，请参阅<https://www.gnu.org/licenses/>
 *
 * 额外注明：
 * 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
 * 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt
 *文件中 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
 * 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明（即本声明）
 *
 * 文件名称          zf_common_function
 * 公司名称          成都逐飞科技有限公司
 * 版本信息          查看 libraries/doc 文件夹内 version 文件 版本说明
 * 开发环境          IAR 9.40.1
 * 适用平台          CYT4BB
 * 店铺链接          https://seekfree.taobao.com/
 *
 * 修改记录
 * 日期              作者                备注
 * 2024-1-4       pudding            first version
 ********************************************************************************************************************/

#include "math.h"

#include "zf_common_debug.h"
#include "zf_common_function.h"

/**
 * @brief 死区处理，常用于消除零点附近的微小误差
 *
 * @param num 要处理的数
 * @param DZ_min 死区范围
 * @param DZ_max 死区范围
 * @param DZ_num 落在死区内时返回的值
 * @return float 处理后的结果
 */
float DeadZone_Process(float num, float DZ_min, float DZ_max, float DZ_num) {
  // 若在死区内则返回死区值
  if (num > DZ_min && num < DZ_max) {
    return DZ_num;
  } else
    return num;
}

/**
 * @brief 线性归一化函数
 *
 * @param data_min 数据的最小值
 * @param data_zero_point 数据锚定的零点值
 * @param data_max 数据的最大值
 * @param data_to_norm 待归一化的数据值
 * @param is_oppositive 是否相反数输出
 * @return float 返回的归一化数值
 * norm_num = normalizeData(MAX, MIN, ZERO, norm_num); // norm_num归一化本身
 */
float normalizeData(uint32_t data_min, uint32_t data_zero_point,
                    uint32_t data_max, uint32_t data_to_norm,
                    bool is_oppositive) {
  data_to_norm = func_limit_ab(data_to_norm, data_min, data_max); // 先限幅
  float res = 0;
  if (data_to_norm < data_zero_point) {
    res = ((float)data_to_norm - (float)data_zero_point) /
          ((float)data_zero_point - (float)data_min);
  } else {
    res = ((float)data_to_norm - (float)data_zero_point) /
          ((float)data_max - (float)data_zero_point);
  }
  if (is_oppositive) {
    res = -res;
  }
  return res;
}

/**
 * @brief 反归一化函数
 *
 * @param data_min 下边界
 * @param data_zero_point 零点
 * @param data_max 上边界
 * @param data_to_anti_norm 输入的归一化数字
 * @param is_opposite 是否反向归一化
 * @return float 输出的反归一数值
 */
float antiNormalizeData(const float data_min, const float data_zero_point,
                        const float data_max, float data_to_anti_norm,
                        bool is_opposite) {
  data_to_anti_norm = func_limit_ab(data_to_anti_norm, -1, 1); // 先限幅
  float anti_norm_res = 0;

  if (data_to_anti_norm < 0) {
    anti_norm_res =
        (data_to_anti_norm * (data_zero_point - data_min) + data_zero_point);
  } else {
    anti_norm_res =
        (data_to_anti_norm * (data_max - data_zero_point) + data_zero_point);
  }
  if (is_opposite) {
    anti_norm_res = -anti_norm_res;
  }
  return anti_norm_res;
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     正弦波转换函数 获取指定采样点
// 参数说明     *data_buffer    数据缓冲区
// 参数说明     sample_max      采样点数
// 参数说明     amplitude_max   最大幅值
// 参数说明     offset_degree   偏移相位角
// 返回参数     void
// 使用示例     func_get_sin_amplitude_table(sound_amplitude, 1024, 512, 270);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void func_get_sin_amplitude_table(uint32 *data_buffer, uint32 sample_max,
                                  uint32 amplitude_max, uint32 offset_degree) {
  uint32 i = 0, j = 0;
  double rad = 0.0;
  double amplitude = 0.0;

  offset_degree = offset_degree % 360;
  offset_degree = (uint32)((float)offset_degree / 360.0 * sample_max);

  j = amplitude_max / 2; // 偏置幅值 默认为一半最大幅值
  rad = 3.1415926535898 * 2 / sample_max; // 换算每个采样点的弧度差
  for (i = offset_degree; i < sample_max + offset_degree; i++) {
    amplitude = j * sin(rad * i) + j;
    *data_buffer = (uint32)amplitude;
    data_buffer++;
  }
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     获取整型数的最大公约数 九章算术之更相减损术
// 参数说明     num1            数字1
// 参数说明     num2            数字2
// 返回参数     uint32          最大公约数
// 使用示例     return func_get_greatest_common_divisor(144, 36); // 获取 144 与
// 36 的最大公约数 备注信息
//-------------------------------------------------------------------------------------------------------------------
uint32 func_get_greatest_common_divisor(uint32 num1, uint32 num2) {
  while (num1 != num2) {
    if (num1 > num2) {
      num1 = num1 - num2;
    }
    if (num1 < num2) {
      num2 = num2 - num1;
    }
  }
  return num1;
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     软件延时
// 参数说明     t               延时时间
// 返回参数     void
// 使用示例     func_soft_delay(100);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void func_soft_delay(volatile long t) {
  while (t--)
    ;
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     字符串转整形数字 数据范围是 [-32768,32767]
// 参数说明     *str            传入字符串 可带符号
// 返回参数     int32           转换后的数据
// 使用示例     int32 dat = func_str_to_int("-100");
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
int32 func_str_to_int(char *str) {
  zf_assert(NULL != str);
  uint8 sign = 0; // 标记符号 0-正数 1-负数
  int32 temp = 0; // 临时计算变量
  do {
    if (NULL == str) {
      break;
    }

    if ('-' == *str) // 如果第一个字符是负号
    {
      sign = 1; // 标记负数
      str++;
    } else if ('+' == *str) // 如果第一个字符是正号
    {
      str++;
    }

    while (('0' <= *str) && ('9' >= *str)) // 确定这是个数字
    {
      temp = temp * 10 + ((uint8)(*str) - 0x30); // 计算数值
      str++;
    }

    if (sign) {
      temp = -temp;
    }
  } while (0);
  return temp;
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     整形数字转字符串 数据范围是 [-32768,32767]
// 参数说明     *str            字符串指针
// 参数说明     number          传入的数据
// 返回参数     void
// 使用示例     func_int_to_str(data_buffer, -300);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void func_int_to_str(char *str, int32 number) {
  zf_assert(NULL != str);
  uint8 data_temp[16]; // 缓冲区
  uint8 bit = 0;       // 数字位数
  int32 number_temp = 0;

  do {
    if (NULL == str) {
      break;
    }

    if (0 > number) // 负数
    {
      *str++ = '-';
      number = -number;
    } else if (0 == number) // 或者这是个 0
    {
      *str = '0';
      break;
    }

    while (0 != number) // 循环直到数值归零
    {
      number_temp = number % 10;
      data_temp[bit++] = func_abs(number_temp); // 倒序将数值提取出来
      number /= 10;                             // 削减被提取的个位数
    }
    while (0 != bit) // 提取的数字个数递减处理
    {
      *str++ = (data_temp[bit - 1] +
                0x30); // 将数字从倒序数组中倒序取出 变成正序放入字符串
      bit--;
    }
  } while (0);
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     字符串转整形数字 数据范围是 [0,65535]
// 参数说明     *str            传入字符串 无符号
// 返回参数     uint32          转换后的数据
// 使用示例     uint32 dat = func_str_to_uint("100");
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
uint32 func_str_to_uint(char *str) {
  zf_assert(NULL != str);
  uint32 temp = 0; // 临时计算变量

  do {
    if (NULL == str) {
      break;
    }

    while (('0' <= *str) && ('9' >= *str)) // 确定这是个数字
    {
      temp = temp * 10 + ((uint8)(*str) - 0x30); // 计算数值
      str++;
    }
  } while (0);

  return temp;
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     整形数字转字符串 数据范围是 [0,65535]
// 参数说明     *str            字符串指针
// 参数说明     number          传入的数据
// 返回参数     void
// 使用示例     func_uint_to_str(data_buffer, 300);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
void func_uint_to_str(char *str, uint32 number) {
  zf_assert(NULL != str);
  int8 data_temp[16]; // 缓冲区
  uint8 bit = 0;      // 数字位数

  do {
    if (NULL == str) {
      break;
    }

    if (0 == number) // 这是个 0
    {
      *str = '0';
      break;
    }

    while (0 != number) // 循环直到数值归零
    {
      data_temp[bit++] = (number % 10); // 倒序将数值提取出来
      number /= 10;                     // 削减被提取的个位数
    }
    while (0 != bit) // 提取的数字个数递减处理
    {
      *str++ = (data_temp[bit - 1] +
                0x30); // 将数字从倒序数组中倒序取出 变成正序放入字符串
      bit--;
    }
  } while (0);
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     字符串转浮点数 有效累计精度为小数点后六位
// 参数说明     *str            传入字符串 可带符号
// 返回参数     float           转换后的数据
// 使用示例     float dat = func_str_to_float("-100.2");
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
float func_str_to_float(char *str) {
  zf_assert(NULL != str);
  uint8 sign = 0;         // 标记符号 0-正数 1-负数
  float temp = 0.0;       // 临时计算变量 整数部分
  float temp_point = 0.0; // 临时计算变量 小数部分
  float point_bit = 1;    // 小数累计除数

  do {
    if (NULL == str) {
      break;
    }

    if ('-' == *str) // 负数
    {
      sign = 1; // 标记负数
      str++;
    } else if ('+' == *str) // 如果第一个字符是正号
    {
      str++;
    }

    // 提取整数部分
    while (('0' <= *str) && ('9' >= *str)) // 确定这是个数字
    {
      temp = temp * 10 + ((uint8)(*str) - 0x30); // 将数值提取出来
      str++;
    }
    if ('.' == *str) {
      str++;
      while (('0' <= *str) && ('9' >= *str) &&
             1000000.0 > point_bit) // 确认这是个数字 并且精度控制还没到六位
      {
        temp_point =
            temp_point * 10 + ((uint8)(*str) - 0x30); // 提取小数部分数值
        point_bit *= 10; // 计算这部分小数的除数
        str++;
      }
      temp_point /= point_bit; // 计算小数
    }
    temp += temp_point; // 将数值拼合

    if (sign) {
      temp = -temp;
    }
  } while (0);
  return temp;
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     浮点数字转字符串
// 参数说明     *str            字符串指针
// 参数说明     number          传入的数据
// 参数说明     point_bit       小数点精度
// 返回参数     void
// 使用示例     func_float_to_str(data_buffer, 3.1415, 2); // 结果输出
// data_buffer = "3.14" 备注信息
//-------------------------------------------------------------------------------------------------------------------
void func_float_to_str(char *str, float number, uint8 point_bit) {
  zf_assert(NULL != str);
  int data_int = 0;       // 整数部分
  int data_float = 0.0;   // 小数部分
  int data_temp[8];       // 整数字符缓冲
  int data_temp_point[6]; // 小数字符缓冲
  uint8 bit = point_bit;  // 转换精度位数

  do {
    if (NULL == str) {
      break;
    }

    // 提取整数部分
    data_int = (int)number; // 直接强制转换为 int
    if (0 > number)         // 判断源数据是正数还是负数
    {
      *str++ = '-';
    } else if (0.0 == number) // 如果是个 0
    {
      *str++ = '0';
      *str++ = '.';
      *str = '0';
      break;
    }

    // 提取小数部分
    number = number - data_int; // 减去整数部分即可
    while (bit--) {
      number = number * 10; // 将需要的小数位数提取到整数部分
    }
    data_float = (int)number; // 获取这部分数值

    // 整数部分转为字符串
    bit = 0;
    do {
      data_temp[bit++] = data_int % 10; // 将整数部分倒序写入字符缓冲区
      data_int /= 10;
    } while (0 != data_int);
    while (0 != bit) {
      *str++ = (func_abs(data_temp[bit - 1]) +
                0x30); // 再倒序将倒序的数值写入字符串 得到正序数值
      bit--;
    }

    // 小数部分转为字符串
    if (0 != point_bit) {
      bit = 0;
      *str++ = '.';
      if (0 == data_float) {
        *str = '0';
      } else {
        while (0 != point_bit) // 判断有效位数
        {
          data_temp_point[bit++] = data_float % 10; // 倒序写入字符缓冲区
          data_float /= 10;
          point_bit--;
        }
        while (0 != bit) {
          *str++ = (func_abs(data_temp_point[bit - 1]) +
                    0x30); // 再倒序将倒序的数值写入字符串 得到正序数值
          bit--;
        }
      }
    }
  } while (0);
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     字符串转浮点数 有效累计精度为小数点后九位
// 参数说明     str             传入字符串 可带符号
// 返回参数     double          转换后的数据
// 使用示例     double dat = func_str_to_double("-100.2");
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
double func_str_to_double(char *str) {
  zf_assert(NULL != str);
  uint8 sign = 0;          // 标记符号 0-正数 1-负数
  double temp = 0.0;       // 临时计算变量 整数部分
  double temp_point = 0.0; // 临时计算变量 小数部分
  double point_bit = 1;    // 小数累计除数

  do {
    if (NULL == str) {
      break;
    }

    if ('-' == *str) // 负数
    {
      sign = 1; // 标记负数
      str++;
    } else if ('+' == *str) // 如果第一个字符是正号
    {
      str++;
    }

    // 提取整数部分
    while (('0' <= *str) && ('9' >= *str)) // 确定这是个数字
    {
      temp = temp * 10 + ((uint8)(*str) - 0x30); // 将数值提取出来
      str++;
    }
    if ('.' == *str) {
      str++;
      while (('0' <= *str) && ('9' >= *str) &&
             1000000000.0 > point_bit) // 确认这是个数字 并且精度控制还没到九位
      {
        temp_point =
            temp_point * 10 + ((uint8)(*str) - 0x30); // 提取小数部分数值
        point_bit *= 10; // 计算这部分小数的除数
        str++;
      }
      temp_point /= point_bit; // 计算小数
    }
    temp += temp_point; // 将数值拼合

    if (sign) {
      temp = -temp;
    }
  } while (0);
  return temp;
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     浮点数字转字符串
// 参数说明     *str            字符串指针
// 参数说明     number          传入的数据
// 参数说明     point_bit       小数点精度
// 返回参数     void
// 使用示例     func_double_to_str(data_buffer, 3.1415, 2); // 结果输出
// data_buffer = "3.14" 备注信息
//-------------------------------------------------------------------------------------------------------------------
void func_double_to_str(char *str, double number, uint8 point_bit) {
  zf_assert(NULL != str);
  int data_int = 0;       // 整数部分
  int data_float = 0.0;   // 小数部分
  int data_temp[12];      // 整数字符缓冲
  int data_temp_point[9]; // 小数字符缓冲
  uint8 bit = point_bit;  // 转换精度位数

  do {
    if (NULL == str) {
      break;
    }

    // 提取整数部分
    data_int = (int)number; // 直接强制转换为 int
    if (0 > number)         // 判断源数据是正数还是负数
    {
      *str++ = '-';
    } else if (0.0 == number) // 如果是个 0
    {
      *str++ = '0';
      *str++ = '.';
      *str = '0';
      break;
    }

    // 提取小数部分
    number = number - data_int; // 减去整数部分即可
    while (bit--) {
      number = number * 10; // 将需要的小数位数提取到整数部分
    }
    data_float = (int)number; // 获取这部分数值

    // 整数部分转为字符串
    bit = 0;
    do {
      data_temp[bit++] = data_int % 10; // 将整数部分倒序写入字符缓冲区
      data_int /= 10;
    } while (0 != data_int);
    while (0 != bit) {
      *str++ = (func_abs(data_temp[bit - 1]) +
                0x30); // 再倒序将倒序的数值写入字符串 得到正序数值
      bit--;
    }

    // 小数部分转为字符串
    if (0 != point_bit) {
      bit = 0;
      *str++ = '.';
      if (0 == data_float) {
        *str = '0';
      } else {
        while (0 != point_bit) // 判断有效位数
        {
          data_temp_point[bit++] = data_float % 10; // 倒序写入字符缓冲区
          data_float /= 10;
          point_bit--;
        }
        while (0 != bit) {
          *str++ = (func_abs(data_temp_point[bit - 1]) +
                    0x30); // 再倒序将倒序的数值写入字符串 得到正序数值
          bit--;
        }
      }
    }
  } while (0);
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     字符串转 Hex
// 参数说明     str             传入字符串 无符号
// 返回参数     uint32          转换后的数据
// 使用示例     uint32 dat = func_str_to_hex("0x11");
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
uint32 func_str_to_hex(char *str) {
  zf_assert(NULL != str);
  uint32 str_len = strlen(str); // 字符串长
  uint32 result_data = 0;       // 结果缓存
  uint8 temp = 0;               // 计算变量
  uint8 flag = 0;               // 标志位

  do {
    if (NULL == str) {
      break;
    }

    if (flag) {
      if (('a' <= *str) && ('f' >= *str)) {
        temp = (*str - 87);
      } else if (('A' <= *str) && ('F' >= *str)) {
        temp = (*str - 55);
      } else if (('0' <= *str) && ('9' >= *str)) {
        temp = (*str - 48);
      } else {
        break;
      }
      result_data = ((result_data << 4) | (temp & 0x0F));
    } else {
      //            if(strncmp("0x", str, 2))
      if (('0' == *str) && ('x' == *(str + 1))) {
        str++;
        flag = 1;
      }
    }
    str++;
  } while (str_len--);

  return result_data;
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     Hex 转字符串
// 参数说明     *str            字符串指针
// 参数说明     number          传入的数据
// 返回参数     void
// 使用示例     func_hex_to_str(data_buffer, 0x11); // 结果输出 data_buffer =
// "0x11" 备注信息
//-------------------------------------------------------------------------------------------------------------------
void func_hex_to_str(char *str, uint32 number) {
  zf_assert(NULL != str);
  const char hex_index[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
                              '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  int8 data_temp[12]; // 缓冲区
  uint8 bit = 0;      // 数字位数

  *str++ = '0';
  *str++ = 'x';
  do {
    if (NULL == str) {
      break;
    }

    if (0 == number) // 这是个 0
    {
      *str = '0';
      break;
    }

    while (0 != number) // 循环直到数值归零
    {
      data_temp[bit++] = (number & 0xF); // 倒序将数值提取出来
      number >>= 4;                      // 削减被提取的个位数
    }
    while (0 != bit) // 提取的数字个数递减处理
    {
      *str++ = hex_index[data_temp[bit - 1]]; // 将数字从倒序数组中倒序取出
                                              // 变成正序放入字符串
      bit--;
    }
  } while (0);
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     数字转换为 ASCII 值
// 参数说明     dat             传入的数据
// 参数说明     *p              数据缓冲
// 参数说明     neg_type        数据类型
// 参数说明     radix           进制
// 返回参数     uint8           数据
// 使用示例     number_conversion_ascii((uint32)ival, vstr, 1, 10);
// 备注信息     本函数在文件内部调用 用户不用关注 也不可修改
//-------------------------------------------------------------------------------------------------------------------
static uint8 number_conversion_ascii(uint32 dat, int8 *p, uint8 neg_type,
                                     uint8 radix) {
  int32 neg_dat = 0;
  uint32 pos_dat = 0;
  uint8 temp_data = 0;
  uint8 valid_num = 0;

  if (neg_type) {
    neg_dat = (int32)dat;
    if (0 > neg_dat) {
      neg_dat = -neg_dat;
    }
    while (1) {
      *p = neg_dat % radix + '0';
      neg_dat = neg_dat / radix;
      valid_num++;

      if (!neg_dat) {
        break;
      }
      p++;
    }
  } else {
    pos_dat = dat;
    while (1) {
      temp_data = pos_dat % radix;
      if (10 <= temp_data) {
        temp_data += 'A' - 10;
      } else {
        temp_data += '0';
      }

      *p = temp_data;

      pos_dat = pos_dat / radix;
      valid_num++;

      if (!pos_dat) {
        break;
      }
      p++;
    }
  }
  return valid_num;
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     printf 显示转换
// 参数说明     *d_buff         缓冲区
// 参数说明     len             长度
// 返回参数     void
// 使用示例     printf_reverse_order(vstr, vlen);
// 备注信息     本函数在文件内部调用 用户不用关注 也不可修改
//-------------------------------------------------------------------------------------------------------------------
static void printf_reverse_order(int8 *d_buff, uint32 len) {
  uint32 i = 0;
  int8 temp_data = 0;
  for (i = 0; len / 2 > i; i++) {
    temp_data = d_buff[len - 1 - i];
    d_buff[len - 1 - i] = d_buff[i];
    d_buff[i] = temp_data;
  }
}

//-------------------------------------------------------------------------------------------------------------------
// 函数简介     sprintf 函数实现
// 参数说明     *buff           缓冲区
// 参数说明     *format         源字符串
// 参数说明     ...             可变参数列表
// 返回参数     uint32          处理后数据长
// 使用示例     zf_sprintf(buff, "Data : %d", 100);
// 备注信息     本函数在文件内部调用 用户不用关注 也不可修改
//-------------------------------------------------------------------------------------------------------------------
uint32 zf_sprintf(int8 *buff, const int8 *format, ...) {
  uint32 buff_len = 0;
  va_list arg;
  va_start(arg, format);

  while (*format) {
    int8 ret = *format;
    if ('%' == ret) {
      switch (*++format) {
      case 'a': // 十六进制p计数法输出浮点数 暂未实现
      {
      } break;

      case 'c': // 一个字符
      {
        int8 ch = (int8)va_arg(arg, uint32);
        *buff = ch;
        buff++;
        buff_len++;
      } break;

      case 'd':
      case 'i': // 有符号十进制整数
      {
        int8 vstr[33];
        int32 ival = (int32)va_arg(arg, int32);
        uint8 vlen = number_conversion_ascii((uint32)ival, vstr, 1, 10);

        if (0 > ival) {
          vstr[vlen] = '-';
          vlen++;
        }
        printf_reverse_order(vstr, vlen);
        memcpy(buff, vstr, vlen);
        buff += vlen;
        buff_len += vlen;
      } break;

      case 'f': // 浮点数，输出小数点后六位  不能指定输出精度
      case 'F': // 浮点数，输出小数点后六位  不能指定输出精度
      {
        int8 vstr[33];
        double ival = (double)va_arg(arg, double);
        uint8 vlen = number_conversion_ascii((uint32)(int32)ival, vstr, 1, 10);

        if (0 > ival) {
          vstr[vlen] = '-';
          vlen++;
        }
        printf_reverse_order(vstr, vlen);
        memcpy(buff, vstr, vlen);
        buff += vlen;
        buff_len += vlen;

        ival = ((double)ival - (int32)ival) * 1000000;
        if (ival) {
          vlen = number_conversion_ascii((uint32)(int32)ival, vstr, 1, 10);
        } else {
          vstr[0] = vstr[1] = vstr[2] = vstr[3] = vstr[4] = vstr[5] = '0';
          vlen = 6;
        }

        while (6 > vlen) {
          vstr[vlen] = '0';
          vlen++;
        }

        vstr[vlen] = '.';
        vlen++;

        printf_reverse_order(vstr, vlen);
        memcpy(buff, vstr, vlen);
        buff_len += vlen;
      } break;

      case 'u': // 无符号十进制整数
      {
        int8 vstr[33];
        uint32 ival = (uint32)va_arg(arg, uint32);
        uint8 vlen = number_conversion_ascii(ival, vstr, 0, 10);

        printf_reverse_order(vstr, vlen);
        memcpy(buff, vstr, vlen);
        buff += vlen;
        buff_len += vlen;
      } break;

      case 'o': // 无符号八进制整数
      {
        int8 vstr[33];
        uint32 ival = (uint32)va_arg(arg, uint32);
        uint8 vlen = number_conversion_ascii(ival, vstr, 0, 8);

        printf_reverse_order(vstr, vlen);
        memcpy(buff, vstr, vlen);
        buff += vlen;
        buff_len += vlen;
      } break;

      case 'x': // 无符号十六进制整数
      case 'X': // 无符号十六进制整数
      {
        int8 vstr[33];
        uint32 ival = (uint32)va_arg(arg, uint32);
        uint8 vlen = number_conversion_ascii(ival, vstr, 0, 16);

        printf_reverse_order(vstr, vlen);
        memcpy(buff, vstr, vlen);
        buff += vlen;
        buff_len += vlen;
      } break;

      case 's': // 字符串
      {
        int8 *pc = va_arg(arg, int8 *);
        while (*pc) {
          *buff = *pc;
          buff++;
          buff_len++;
          pc++;
        }
      } break;

      case 'p': // 以16进制形式输出指针
      {
        int8 vstr[33];
        uint32 ival = (uint32)va_arg(arg, uint32);
        uint8 vlen = number_conversion_ascii(ival, vstr, 0, 16);

        printf_reverse_order(vstr, 8);
        memcpy(buff, vstr, 8);
        buff += 8;
        buff_len += 8;
      } break;

      case '%': // 输出字符%
      {
        *buff = '%';
        buff++;
        buff_len++;
      } break;

      default: {
      } break;
      }
    } else {
      *buff = (int8)(*format);
      buff++;
      buff_len++;
    }
    format++;
  }
  va_end(arg);

  return buff_len;
}
